package cn.com.chengmandian.core.web.service;

import cn.com.chengmandian.core.common.constants.CommonConstant;
import cn.com.chengmandian.core.web.exceptions.BadResponseException;
import cn.com.chengmandian.core.web.pojo.txmap.Direction;
import cn.com.chengmandian.core.web.pojo.txmap.Geocoder;
import cn.com.chengmandian.core.web.pojo.txmap.Response;
import cn.com.chengmandian.core.web.properties.TxMapProperties;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Map;
import java.util.TreeMap;

@ConditionalOnProperty(prefix = "cmd.txmap", name = "enable", havingValue = "true")
@Component
public class TxMapService {

    private static final String SERVER_URL = "https://apis.map.qq.com";
    private static final String GEOCODER_URL = "/ws/geocoder/v1/";
    private static final String DIRECTION_WALKING_URL = "/ws/direction/v1/walking/";
    private static final String DIRECTION_BICYCLING_URL = "/ws/direction/v1/bicycling/";

    @Autowired
    private TxMapProperties txMapProperties;

    public static void main(String[] args) {
        Map<String, String> map = new TreeMap<>();
        map.put("lng", "1");
        map.put("lat", "2");
        map.put("key", "3");
        map.put("to", "4");
        System.out.println(map);
        System.out.println(MapUtil.join(map, "&", "="));
    }

    /**
     * 本接口提供由经纬度到文字地址及相关位置信息的转换能力，广泛应用于物流、出行、O2O、社交等场景。服务响应速度快、稳定，支撑亿级调用。
     * 1）满足传统对省市区、乡镇村、门牌号、道路及交叉口、河流、湖泊、桥、poi列表的需求。
     * 2）提供通过知名地点、地标组合形成的易于理解的地址，如：北京市海淀区中钢国际广场(欧美汇购物中心北)。
     * 3）提供精准的商圈、知名的大型区域、附近知名的一级地标、代表当前位置的二级地标等。
     */
    public Geocoder geocoder(BigDecimal lat, BigDecimal lng) {
        Map<String, String> param = new TreeMap<>();
        param.put("location", lat + "," + lng);
        String result = HttpUtil.get(getSigUrl(GEOCODER_URL, param));
        Response<Geocoder> response = JSONObject.parseObject(result, new TypeReference<Response<Geocoder>>() {});
        if (!response.getStatus().equals(CommonConstant.ZERO)) {
            throw new BadResponseException("TxMapService error：" + response.getMessage());
        }
        return response.getResult();
    }

    /**
     * 腾讯地图Direction API，提供多种交通方式的路线计算能力，包括：
     * 步行（walking）：基于步行路线规划。
     */
    public Direction directionWalking(BigDecimal fromLat, BigDecimal fromLng, BigDecimal toLat, BigDecimal toLng) {
        Map<String, String> param = new TreeMap<>();
        param.put("from", fromLat + "," + fromLng);
        param.put("to", toLat + "," + toLng);
        String result = HttpUtil.get(getSigUrl(DIRECTION_WALKING_URL, param));
        Response<Direction> response = JSONObject.parseObject(result, new TypeReference<Response<Direction>>() {});
        if (!response.getStatus().equals(CommonConstant.ZERO)) {
            throw new BadResponseException("TxMapService error：" + response.getMessage());
        }
        return response.getResult();
    }

    /**
     * 腾讯地图Direction API，提供多种交通方式的路线计算能力，包括：
     * 步行（bicycling）：基于自行车的骑行路线
     */
    public Direction directionBicycling(BigDecimal fromLat, BigDecimal fromLng, BigDecimal toLat, BigDecimal toLng) {
        Map<String, String> param = new TreeMap<>();
        param.put("from", fromLat + "," + fromLng);
        param.put("to", toLat + "," + toLng);
        String result = HttpUtil.get(getSigUrl(DIRECTION_BICYCLING_URL, param));
        Response<Direction> response = JSONObject.parseObject(result, new TypeReference<Response<Direction>>() {});
        if (!response.getStatus().equals(CommonConstant.ZERO)) {
            throw new BadResponseException("TxMapService error：" + response.getMessage());
        }
        return response.getResult();
    }

    /**
     * 附加签名校验
     */
    private String getSigUrl(String url, Map<String, String> param) {
        param.put("key", txMapProperties.getKey());
        url = url + "?" + MapUtil.join(param, "&", "=");
        if (StrUtil.isNotBlank(txMapProperties.getSk())) {
            String sig = SecureUtil.md5(url + txMapProperties.getSk());
            url = url + "&sig=" + sig;
        }
        return SERVER_URL + url;
    }
}
